package com.whisper.view;

import com.sun.awt.AWTUtilities;
import com.whisper.barrage.BarrageEntity;
import com.whisper.utils.RedisQuery;
import com.whisper.utils.SerializeUtil;

import javax.annotation.Resource;
import javax.swing.*;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Semaphore;

/**
 * 桌面弹幕展示
 *
 * @author ysz
 * @date 2024/2/20 14:20
 */
//@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }, scanBasePackages = { "com.whisper.*"})
public class WindowBarrage extends JFrame {

    private static WindowBarrage instacne = null;

    private static Semaphore semaphore = new Semaphore(0);

    private static AffineTransform atf = new AffineTransform();

    private static FontRenderContext frc = new FontRenderContext(atf, true,
            true);

    // 弹幕集
    private List<BarrageEntity> barrageEntities = new ArrayList<>();

    // 窗口宽度
    private int windowWidth;

    // 窗口高度
    private int windowHeight;

    // 移动速度
    private int speed=1;

    // 最大弹幕数
    private int maxScreenDanmuCount=50;

    private int barragesCount;

    public static void main(String[] args) {
        WindowBarrage WindowView = getInstance();
    }

    public static synchronized WindowBarrage getInstance() {
        if (instacne == null) {
            try {
                initPaint();
                semaphore.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return instacne;
    }

    /**
     * 弹幕及输入框容器绘制
     * @author ysz
     * @param
     * @return
     **/
    public WindowBarrage() {
        // 获取桌面大小
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        windowHeight = (int) screenSize.getHeight();
        windowWidth = (int) screenSize.getWidth();

        Rectangle bounds = new Rectangle(screenSize);
        this.setTitle("开摸！");
        this.setLayout(null);
        this.setBounds(bounds);
//        this.setType(JFrame.Type.UTILITY);//隐藏任务栏图标
        this.setExtendedState(Frame.MAXIMIZED_BOTH);
        // 始终最前显示
        this.setAlwaysOnTop(true);
        // 判断是否支持透明度
        this.setUndecorated(true);
        // 禁用或启用此窗体的修饰。只有在窗体不可显示时
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);

        AWTUtilities.setWindowOpaque(this, false);
        this.setVisible(true);

        ImageIcon img = new ImageIcon(WindowBarrage.class.getClassLoader().getResource("img/logo.png"));
        this.setIconImage(img.getImage());
    }

    /**
     * 添加弹幕
     * @author ysz
     * @param barrageEntity
     * @return void
     **/
    public void addBarrage(BarrageEntity barrageEntity) {
        Random random = new Random();
        barrageEntity.y = random.nextInt(windowHeight - 150) + 50;
        barrageEntity.x = windowWidth;

        RedisQuery.getInstance().pushObject("barrage", barrageEntity);
    }

    /**
     * 重写 JFrame 的绘制方法
     * @author ysz
     * @param gg
     * @return void
     **/
    @Override
    public void paint(Graphics gg) {
        super.paint(gg);
        int st = 0;
//        if (barrages.size() > maxScreenDanmuCount) {
//            st = barrages.size() - maxScreenDanmuCount;
//        }

        for(int i = st; i < barrageEntities.size(); i++) {
            BarrageEntity text = barrageEntities.get(i);
            if (text.x < -windowWidth) {
                continue;
            }

            Font font = new Font("微软雅黑",text.getStyle(), text.getSize());
            gg.setColor(Color.gray);
            gg.fillRoundRect(text.x - 8, text.y - 14, (int) font.getStringBounds(text.getText(), frc).getWidth() + 16, 22, 1, 1);
            gg.setColor(Color.WHITE);
            gg.setFont(font);
            gg.drawString(text.getText(), text.x, text.y);
        }
    }

    /**
     * 使用 Timer 刷新弹幕
     * @author ysz
     * @param
     * @return void
     **/
    private void paintWindow() {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                // 控制弹幕左移
                int st = 0;
//                if (barrages.size() > maxScreenDanmuCount) {
//                    st = barrages.size() - maxScreenDanmuCount;
//                }
                for(int i = st; i < barrageEntities.size(); i++) {
                    BarrageEntity barrage = barrageEntities.get(i);
                    barrage.x -= speed;
                }
                // 重新绘制
                repaint();
            }
        }, 100,50);
    }

    private static void initPaint() {
        SwingUtilities.invokeLater(() -> {
            // 初始化弹幕窗口
            instacne = new WindowBarrage();
            // 初始化输入框及其它
            instacne.initPaintOther();
            // 同步弹幕
            instacne.syncBarrages();
            // 绘制弹幕及左移
            instacne.paintWindow();
            semaphore.release();
        });
    }

    /**
     * 同步弹幕
     * @author ysz
     * @param
     * @return void
     */
    private void syncBarrages() {
        List<byte[]> barrages = (List) RedisQuery.getInstance().getObjectList("barrage");
        barragesCount = barrages.size();

        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                List<byte[]> barrages = (List) ((List<?>) RedisQuery.getInstance().getObjectList("barrage"));
                // 防止redis重置导致弹幕归零
                if ((barrageEntities.size() + barragesCount) > barrages.size()) {
                    barragesCount = barrages.size() - barrageEntities.size();
                }
                // 当前弹幕=redis所有弹幕-初始弹幕
                barrages = barrages.subList(barrageEntities.size() + barragesCount, barrages.size());
                for (byte[] barrage : barrages) {
                    barrageEntities.add((BarrageEntity) SerializeUtil.unSerialize(barrage));
                }
            }
        }, 100,30);
    }

    /**
     * 绘制其它画布内容
     */
    public void initPaintOther() {
        // 绘制输入框
        new GlassPaneInput().paintInputPane(this);
//        new Tray().paintTray(this);
    }
}

